-----------------------------------------------------------------------------------------------
-- Client Lua Script for Raiderino
-- Copyright (c) James Parker 2014. All rights reserved
-----------------------------------------------------------------------------------------------
 
require "Window"
require "Sound"
 
local Raiderino = {} 
 
-----------------------------------------------------------------------------------------------
-- Initialization
-----------------------------------------------------------------------------------------------
function Raiderino:new(o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self 

	return o
end

function Raiderino:Init()
	local bHasConfigureFunction = false
	local strConfigureButtonText = ""
	local tDependencies = {
	}
	Apollo.RegisterAddon(self, bHasConfigureFunction, strConfigureButtonText, tDependencies)
end
 

-----------------------------------------------------------------------------------------------
-- Raiderino OnLoad
-----------------------------------------------------------------------------------------------
function Raiderino:OnLoad()
	Apollo.LoadSprites("Textures.xml")
	self.xmlDoc = XmlDoc.CreateFromFile("Raiderino.xml")
	self.xmlDoc:RegisterCallback("OnDocLoaded", self)
end

-----------------------------------------------------------------------------------------------
-- Raiderino OnDocLoaded
-----------------------------------------------------------------------------------------------
function Raiderino:OnDocLoaded()
	if self.xmlDoc ~= nil and self.xmlDoc:IsLoaded() then
		self.wndMain = Apollo.LoadForm(self.xmlDoc, "RaiderinoForm", nil, self)
		if self.wndMain == nil then
			Apollo.AddAddonErrorText(self, "Could not load the main window for some reason.")
			return
		end
		
		self.wndMain:Show(false, true)

		self.InternalChannel = ICCommLib.JoinChannel("Raiderino", "OnICCommReceived", self)
		
		local strCancel = Apollo.GetString(1)
		if strCancel == "Abbrechen" then
			self.Locale = 2
		elseif strCancel == "Annuler" then
			self.Locale = 3
		else
			self.Locale = 1
		end

		self.L = {}
		for str, strlocales in pairs(RaiderinoLibs.Locales) do
			self.L[str] = strlocales[self.Locale]
		end

		for unitname, encounterdata in pairs(RaiderinoLibs.Encounters) do
			encounterdata.locname = self.L[unitname]
			for feature,featuredata in pairs(encounterdata.features) do
				featuredata.displayname = self.L[feature]
			end
		end

		self.fBossFunction = nil
		self.tUnits = {}
		self.tTimersCheck = {}
		self.tUntimedCasts = {}
		self.tNPCSay = {}
		self.tDatachron = {}
		self.tNPCSayHandlers = {}
		self.tDatachronHandlers = {}
		self.bDevDebug = false
		self.nFightStartTime = nil
		self.zonetimer = ApolloTimer.Create(1, false, "OnZoneTimer", self)

		self.notifications = RaiderinoLibs.DisplayBlock.new(self.xmlDoc)
		self.notifications:SetName("Notifications")
		self.notifications:SetPosition(0.3, 0.5)
		self.notifications:AnchorFromTop(true)
		self.notifications.contentSoundNew = "Sound\\NotifyNew2.wav"
		self.notifications.contentSoundEnds = "Sound\\NotifyEnds2.wav"

		self.timers = RaiderinoLibs.DisplayBlock.new(self.xmlDoc)
		self.timers:SetName("Timers")
		self.timers:SetPosition(0.5, 0.5)
		self.timers:AnchorFromTop(true)
		self.timers.contentSoundNew = "Sound\\TimerNew2.wav"
		self.timers.contentSoundEnds = "Sound\\TimerEnds2.wav"

		self.unitframe = RaiderinoLibs.UnitsBlock.new(self.xmlDoc)
		self.unitframe:SetName("Units")
		self.unitframe:SetPosition(0.7, 0.5)
		self.unitframe:AnchorFromTop(true)

		if self.saveData ~= nil then
			self:LoadSaveData(self.saveData)
		end

		self.colorPicker = RaiderinoLibs.ColorPicker.new(self.xmlDoc)

		self.UpdateTimer = ApolloTimer.Create(0.1, true, "OnUpdate", self)
		self.UpdateTimer:Stop()

		Apollo.RegisterEventHandler("ChangeWorld", "OnWorldChange", self)
		Apollo.RegisterEventHandler("InterfaceMenuListHasLoaded", "OnInterfaceMenuListHasLoaded", self)
		Apollo.RegisterEventHandler("RaiderinoInterfaceMenuClick", "OnRaiderinoInterfaceMenuClick", self)
		Apollo.RegisterSlashCommand("raiderino", "OnRaiderinoOn", self)
		Apollo.RegisterSlashCommand("Rpull", "OnRpull", self)
		

		self:InitializeConfigForm()

		self.Loaded = true
	end
end

--------------------
-- GUI MANAGEMENT --
--------------------
function Raiderino:InitializeConfigForm()
	local groupOptionsList = self.wndMain:FindChild("GroupOptionsList")
	groupOptionsList:DestroyChildren()
	local notificationsOptions = Apollo.LoadForm(self.xmlDoc, "SubForms.GroupOptions", groupOptionsList, self)
	notificationsOptions:SetData(self.notifications)
	notificationsOptions:FindChild("OptionsLabel"):SetText("Notifications Options")
	self:InitializeGroup(notificationsOptions, self.notifications)
	local timersOptions = Apollo.LoadForm(self.xmlDoc, "SubForms.GroupOptions", groupOptionsList, self)
	timersOptions:SetData(self.timers)
	timersOptions:FindChild("OptionsLabel"):SetText("Timers Options")
	self:InitializeGroup(timersOptions, self.timers)
	local unitframeOptions = Apollo.LoadForm(self.xmlDoc, "SubForms.GroupOptions", groupOptionsList, self)
	unitframeOptions:SetData(self.unitframe)
	unitframeOptions:FindChild("OptionsLabel"):SetText("Units Options")
	self:InitializeGroup(unitframeOptions, self.unitframe)
	groupOptionsList:ArrangeChildrenVert()

	local EncounterZonesList = self.wndMain:FindChild("EncounterZonesList")
	EncounterZonesList:DestroyChildren()
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Genetic Archives - Act 1")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Genetic Archives - Act 2")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Halls of the Infinite Mind")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Stormtalon's Lair")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Ruins of Kel Voreth")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Skullcano Island")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Sanctuary of the Swordmaiden")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("War of the Wilds")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Siege of Tempest Refuge")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Crimelords of Whitevale")
	local zonebar = Apollo.LoadForm(self.xmlDoc, "SubForms.ZoneButton", EncounterZonesList, self)
	zonebar:FindChild("Button"):SetText("Malgrave Trail")
	EncounterZonesList:ArrangeChildrenVert()

	if self.bDevDebug then
		self.wndMain:FindChild("AdvancedTimersButton"):SetText("DEV: Debug Off")
	else
		self.wndMain:FindChild("AdvancedTimersButton"):SetText("DEV: Debug On")
	end

	local EncountersList = self.wndMain:FindChild("EncountersList")
	EncountersList:DestroyChildren()

	local FeaturesList = self.wndMain:FindChild("FeaturesList")
	FeaturesList:DestroyChildren()
end

function Raiderino:InitializeGroup(groupFrame, group)
	groupFrame:FindChild("Enabled"):SetCheck(group:IsEnabled())
	groupFrame:FindChild("BackgroundColor"):FindChild("Text"):SetTextColor(group.bgColor)
	groupFrame:FindChild("BarColor"):FindChild("Text"):SetTextColor(group.barColor)
	groupFrame:FindChild("StartFromTop"):SetCheck(group.anchorFromTop)
	groupFrame:FindChild("BarWidth"):SetValue(group.barSize.Width)
	groupFrame:FindChild("BarWidthValue"):SetText(string.format("%.f", group.barSize.Width))
	groupFrame:FindChild("BarHeight"):SetValue(group.barSize.Height)
	groupFrame:FindChild("BarHeightValue"):SetText(string.format("%.f", group.barSize.Height))
end
---------------------
-- /GUI MANAGEMENT --
---------------------

----------------------
-- SAVE AND RESTORE --
----------------------
function Raiderino:OnSave(eLevel)
	if eLevel ~= GameLib.CodeEnumAddonSaveLevel.Character then
		return nil
	end
	local encounterssave = {}
	for encounter, encounterdata in pairs(RaiderinoLibs.Encounters) do
		encounterssave[encounter] = {}
		encounterssave[encounter].enabled = encounterdata.enabled
		encounterssave[encounter].features = {}
		for feature, featuredata in pairs(encounterdata.features) do
			encounterssave[encounter].features[feature] = {}
			encounterssave[encounter].features[feature].enabled = featuredata.enabled
		end
	end
	local saveData = { 
		notifications = self.notifications:GetSaveData(),
		timers = self.timers:GetSaveData(),
		unitframe = self.unitframe:GetSaveData(),
		encounters = encounterssave,
		bDevDebug = self.bDevDebug
	}
	
	return saveData
end

function Raiderino:OnRestore(eLevel, tData)
	if eLevel ~= GameLib.CodeEnumAddonSaveLevel.Character then
		return nil
	end

	if self.Loaded then
		self:LoadSaveData(tData)
		self:InitializeConfigForm()
	else
		self.saveData = tData
	end
end

function Raiderino:LoadSaveData(tData)
	if tData.notifications then
		self.notifications:Load(tData.notifications)
	end

	if tData.timers then
		self.timers:Load(tData.timers)
	end

	if tData.unitframe then
		self.unitframe:Load(tData.unitframe)
	end

	if tData.encounters then
		for encounter, encounterdata in pairs(tData.encounters) do
			if RaiderinoLibs.Encounters[encounter] then
				RaiderinoLibs.Encounters[encounter].enabled = encounterdata.enabled
				for feature, featuredata in pairs(encounterdata.features) do
					if RaiderinoLibs.Encounters[encounter].features[feature] then
						RaiderinoLibs.Encounters[encounter].features[feature].enabled = featuredata.enabled
					end
				end
			end
		end
	end

	if tData.bDevDebug then
		self.bDevDebug = tData.bDevDebug
	end
end
-----------------------
-- /SAVE AND RESTORE --
-----------------------

--------------------
-- SLASH COMMANDS --
--------------------
function Raiderino:OnRaiderinoOn()
	self:InitializeConfigForm()
	self.wndMain:Invoke()
end

function Raiderino:OnRpull(command, str)
	local duration = tonumber(str)
	local msg = {command = "Pull", sender = GameLib.GetPlayerUnit():GetId(), maxtime = duration}
	self.InternalChannel:SendMessage(msg)
	local options = {text = "PULL IN", maxtime = duration, icon = nil, destroyAtEnd = true}
	self.notifications:AddTimer(options)
end
---------------------
-- /SLASH COMMANDS --
---------------------

---------------------
-- EVENT FUNCTIONS --
---------------------
function Raiderino:OnWorldChange()
	self.zonetimer:Start()
end

function Raiderino:OnZoneTimer()
	local zonemap = GameLib.GetCurrentZoneMap()
	if zonemap then
		self.sCurrZoneName = zonemap.strName
	else
		self.zonetimer:Start()
	end
	local zonesupported = false
	for encounter, encounterdata in pairs(RaiderinoLibs.Encounters) do
		if self.L[encounterdata.zone] == self.sCurrZoneName then
			zonesupported = true
			break
		end
	end
	if zonesupported then
		if self.bDevDebug then
			Print("Raiderino: Known zone,starting event handlers.")
		end
		self.UpdateTimer:Start()
		Apollo.RegisterEventHandler("UnitCreated", "OnUnitCreated", self)
		Apollo.RegisterEventHandler("UnitDestroyed", "OnUnitDestroyed", self)
		Apollo.RegisterEventHandler("UnitEnteredCombat", "OnEnteredCombat", self)
		Apollo.RegisterEventHandler("ChatMessage","OnChatMessage", self)
	else
		if self.bDevDebug then
			Print("Raiderino: Unknown zone,stopping event handlers.")
		end
		self.UpdateTimer:Stop()
		Apollo.RemoveEventHandler("UnitCreated", self)
		Apollo.RemoveEventHandler("UnitDestroyed", self)
		Apollo.RemoveEventHandler("UnitEnteredCombat", self)
		Apollo.RemoveEventHandler("ChatMessage", self)
	end
end

function Raiderino:OnUpdate()
	local player = GameLib.GetPlayerUnit()
	local currTime = GameLib.GetGameTime()
	if player then
		if self.notifications.content["PULL IN"] and not self.notifications.content["PULL IN"].notified then
			if self.notifications.content["PULL IN"].EndTime - currTime < 1 then
				Sound.PlayFile(self.notifications.contentSoundEnds)
				self.notifications.content["PULL IN"].notified = true
			end
		end
		
		self.notifications:ProcessTimers()
		self.timers:ProcessTimers()
		self.unitframe:ProcessUnits()
		if self.fBossFunction then
			self.fBossFunction(self.tUnits)
		end
	end
end

function Raiderino:OnTest()
	if self.unitframe.content[GameLib.GetPlayerUnit():GetId()] then
		self.unitframe.content[GameLib.GetPlayerUnit():GetId()].Frame:Destroy()
		self.unitframe.content[GameLib.GetPlayerUnit():GetId()] = nil
	end
	self.UpdateTimer:Stop()
end

function Raiderino:OnEnteredCombat(unit, bInCombat)
	if unit:GetId() == GameLib.GetPlayerUnit():GetId() then
		if not bInCombat then
			self.timers:ClearAll()
			self.notifications:ClearAll()
			self.unitframe:ClearAll()
			self.tNPCSayHandlers = {}
			self.tDatachronHandlers = {}
			self.fBossFunction = nil
			
			if self.bDevDebug then
				Print("Raiderino: Player left combat.")
				Print("Raiderino: Clearing timers,notifications,unitframes.")
				Print("Raiderino: Removing NPCSay and Datachron handlers.")
				Print("Raiderino: Resetting boss function.")
				local next = next
				if next(self.tNPCSay) then
					Print("++++++++++++++++++++++++++++++")
					Print("++++++ NPC Phrases")
					Print("++++++++++++++++++++++++++++++")
					for phrase, phrasedata in pairs(self.tNPCSay) do
						Print("++ " .. phrase)
						local phrasesline = ""
						for i=1, #phrasedata do
							phrasesline = phrasesline .. " " .. string.format("%.1fs", phrasedata[i])
						end
						Print("++" .. phrasesline)
					end
					Print("++++++++++++++++++++++++++++++")
				end
				if next(self.tDatachron) then
					Print("++++++++++++++++++++++++++++++")
					Print("++++++ Datacron")
					Print("++++++++++++++++++++++++++++++")
					for phrase, phrasedata in pairs(self.tDatachron) do
						Print("++ " .. phrase)
						local phrasesline = ""
						for i=1, #phrasedata do
							phrasesline = phrasesline .. " " .. string.format("%.1fs", phrasedata[i])
						end
						Print("++" .. phrasesline)
					end
					Print("++++++++++++++++++++++++++++++")
				end
				if next(self.tTimersCheck) then
					Print("++++++++++++++++++++++++++++++")
					Print("++++++ Casttimers check")
					Print("++++++++++++++++++++++++++++++")
					for castname, castdata in pairs(self.tTimersCheck) do
						Print("++ " .. castname)
						local castsline = ""
						for i=1, #castdata do
							castsline = castsline .. " " .. string.format("%.1fs", castdata[i])
						end
						Print("++" .. castsline)
					end
					Print("++++++++++++++++++++++++++++++")
				end
				for unitname, castdata in pairs(self.tUntimedCasts) do
					Print("++ Unit: " .. unitname)
					Print("++++++++++++++++++++++++++++++")
					Print("++++ Casts without timers")
					Print("++++++++++++++++++++++++++++++")
					for castname, _ in pairs(castdata) do
						Print("++ " .. castname)
					end
					Print("++++++++++++++++++++++++++++++")
				end
			end
			self.tTimersCheck = {}
			self.tUntimedCasts = {}
			self.tNPCSay = {}
			self.tDatachron = {}
			for encounter, encounterdata in pairs(RaiderinoLibs.Encounters) do
				encounterdata.phase = 1
			end
			if self.bDevDebug then
				Print("Raiderino: Purging timer check table.")
				Print("Raiderino: Purging untimed casts table.")
				Print("Raiderino: Purging NPCSay and Datachron tables.")
			end
		else
			if self.bDevDebug then
				Print("Raiderino: Player entered combat.")
			end
			self.nFightStartTime = GameLib.GetGameTime()
		end
	elseif bInCombat then
		for encounter, encounterdata in pairs(RaiderinoLibs.Encounters) do
			if encounterdata.enabled and unit:GetName() == encounterdata.locname then
				self.fBossFunction = encounterdata.fBossFunction
				if encounterdata.fOnStartCombat then
					encounterdata.fOnStartCombat()
				end
				local options = {unit = unit, HealthMax = unit:GetMaxHealth(), HealthCurrent = unit:GetHealth(), text = unit:GetName()}
				self.unitframe:AddUnit(options)
				if self.bDevDebug then
					Print("Raiderino: Boss " .. encounterdata.locname .. " entered combat.")
					Print("Raiderino: Executing start combat function.")
					Print("Raiderino: Adding boss unitframe.")
				end
				break
			end
		end
	end
end

function Raiderino:OnChatMessage(channelCurrent, tMessage)
	if channelCurrent:GetName() == "NPC Say" then
		for encounter, encounterdata in pairs(RaiderinoLibs.Encounters) do
			if tMessage.strSender == encounterdata.locname then
				if not self.tNPCSay[tMessage.arMessageSegments[1].strText] then
					self.tNPCSay[tMessage.arMessageSegments[1].strText] = {}
					self.tNPCSay[tMessage.arMessageSegments[1].strText][1] = GameLib.GetGameTime() - self.nFightStartTime
				else
					local lastindex = #self.tNPCSay[tMessage.arMessageSegments[1].strText]
					self.tNPCSay[tMessage.arMessageSegments[1].strText][lastindex+1] = GameLib.GetGameTime() - self.nFightStartTime
				end
			end
		end
		for message, handlerfunction in pairs(self.tNPCSayHandlers) do
			if self.bDevDebug then
				Print("Raiderino: Comparing NPC message to handler.")
				Print("Raiderino: Message - " .. tMessage.arMessageSegments[1].strText)
				Print("Raiderino: Handler - " .. self.L[message])
			end
			if self.L[message] == tMessage.arMessageSegments[1].strText then
				if self.bDevDebug then
					Print("Raiderino: Handler found,executing handler function.")
				end
				handlerfunction()
			end
		end
	elseif channelCurrent:GetName() == "Datachron" then
		if GameLib.GetPlayerUnit():IsInCombat() then
			if not self.tDatachron[tMessage.arMessageSegments[1].strText] then
				self.tDatachron[tMessage.arMessageSegments[1].strText] = {}
				self.tDatachron[tMessage.arMessageSegments[1].strText][1] = GameLib.GetGameTime() - self.nFightStartTime
			else
				local lastindex = #self.tDatachron[tMessage.arMessageSegments[1].strText]
				self.tDatachron[tMessage.arMessageSegments[1].strText][lastindex+1] = GameLib.GetGameTime() - self.nFightStartTime
			end
		end
		for message, handlerfunction in pairs(self.tDatachronHandlers) do
			if self.bDevDebug then
				Print("Raiderino: Comparing Datachron message to handler.")
				Print("Raiderino: Message - " .. tMessage.arMessageSegments[1].strText)
				Print("Raiderino: Handler - " .. self.L[message])
			end
			if self.L[message] == tMessage.arMessageSegments[1].strText then
				if self.bDevDebug then
					Print("Raiderino: Handler found,executing handler function.")
				end
				handlerfunction()
			end
		end
	end
end

function Raiderino:OnUnitCreated(unit)
	for encounter, encounterdata in pairs(RaiderinoLibs.Encounters) do
		if unit:GetName() == encounterdata.locname then
			local currcast = nil
			if unit:IsCasting() then
				currcast = unit:GetCastName()
			end
			self.tUnits[unit:GetId()] = {unit = unit, currcastName = currcast}
			if self.fBossFunction == encounterdata.fBossFunction then
				local options = {unit = unit, HealthMax = unit:GetMaxHealth(), HealthCurrent = unit:GetHealth(), text = unit:GetName()}
				self.unitframe:AddUnit(options)
			end
			if self.bDevDebug then
				Print("Raiderino: New boss unit - " .. encounterdata.locname)
			end
			break
		end
	end
	
	if RaiderinoLibs.Encounters["Phage Maw"].features["Bombs"] and self.fBossFunction == RaiderinoLibs.Encounters["Phage Maw"].fBossFunction then
		if unit:GetName() == self.L["Detonation Bomb"] then
			local options = {unit = unit, HealthMax = unit:GetMaxHealth(), HealthCurrent = unit:GetHealth(), text = unit:GetName()}
			self.unitframe:AddUnit(options)
		end
	end
end

function Raiderino:OnUnitDestroyed(unit)
	local unitid = unit:GetId()
	if self.tUnits[unitid] then
		if self.bDevDebug then
			Print("Raiderino: Removing unit - " .. self.tUnits[unitid].unit:GetName())
		end
		self.tUnits[unitid] = nil
	end
end

function Raiderino:OnICCommReceived(chan, msg)
	if msg.command == "Pull" then
		if msg.sender and GameLib.GetUnitById(msg.sender) and GameLib.GetUnitById(msg.sender):IsInYourGroup() then
			if msg.maxtime then
				local options = {text = "PULL IN", maxtime = msg.maxtime, icon = nil, destroyAtEnd = true}
				self.notifications:AddTimer(options)
			end
		end
	end
end

function Raiderino:OnRaiderinoInterfaceMenuClick()
	self:OnRaiderinoOn()
end
----------------------
-- /EVENT FUNCTIONS --
----------------------

-------------
-- METHODS --
-------------
function Raiderino:CastTimingsAdd(castname)
	if not self.tTimersCheck[castname] then
		self.tTimersCheck[castname] = {}
		self.tTimersCheck[castname][1] = GameLib.GetGameTime() - self.nFightStartTime
	else
		local lastindex = #self.tTimersCheck[castname]
		self.tTimersCheck[castname][lastindex+1] = GameLib.GetGameTime() - self.nFightStartTime
	end
end

function Raiderino:UntimedCastAdd(unitname,castname)
	if not self.tUntimedCasts[unitname] then
		self.tUntimedCasts[unitname] = {}
	end
	self.tUntimedCasts[unitname][castname] = true
end

function Raiderino:GetCast(unitid,unit)
	if unit:IsCasting() then
		local castname = unit:GetCastName()
		if self.tUnits[unitid].currcastName ~= castname then
			self.tUnits[unitid].currcastName = castname
			self:CastTimingsAdd(castname)
			return castname
		end
	else
		self.tUnits[unitid].currcastName = nil
		return
	end
end

function Raiderino:GetHealthPercent(unit)
	local CurrHealth = unit:GetHealth()
	local MaxHealth = unit:GetMaxHealth()
	if CurrHealth and MaxHealth then
		return CurrHealth/MaxHealth*100
	end
end

function Raiderino:FeatureCheck(unitname, feature)
	return RaiderinoLibs.Encounters[unitname].features[feature].enabled
end

function Raiderino:PhaseSwitch(unitname, phase)
	RaiderinoLibs.Encounters[unitname].phase = phase
	local phasefunction = RaiderinoLibs.Encounters[unitname].fPhaseFunction
	if phasefunction then
		phasefunction(phase)
	end
end

function Raiderino:GetPhase(unitname)
	return RaiderinoLibs.Encounters[unitname].phase
end

function Raiderino:AddDatachronHandler(message,func)
	self.tDatachronHandlers[message] = func
end
--------------
-- /METHODS --
--------------

--------------------
-- FORM FUNCTIONS --
--------------------
function Raiderino:OnInterfaceMenuListHasLoaded()
	Event_FireGenericEvent("InterfaceMenuList_NewAddOn", "Raiderino", {"RaiderinoInterfaceMenuClick", "", ""})
end

local function SortEncounters(a, b)
	return a:GetData().position < b:GetData().position
end

function Raiderino:OnOK()
	self.wndMain:Close()
end

function Raiderino:OnGroupEnabledChanged( wndHandler, wndControl, eMouseButton )
	local group = wndHandler:GetParent():GetData()
	group:SetEnabled(wndHandler:IsChecked())
end

function Raiderino:OnResetToDefaults( wndHandler, wndControl, eMouseButton )
	self.notifications:ResetPosition()
	self.notifications:SetBarWidth(300)
	self.notifications:SetBarHeight(28)
	self.notifications:SetBGColor(CColor.new(0,0,0,1))
	self.notifications:SetBarColor(CColor.new(1,0,0,0.5))
	self.notifications:SetEnabled(true)
	
	self.timers:ResetPosition()
	self.timers:SetBarWidth(300)
	self.timers:SetBarHeight(28)
	self.timers:SetBGColor(CColor.new(0,0,0,1))
	self.timers:SetBarColor(CColor.new(1,0,0,0.5))
	self.timers:SetEnabled(true)
	
	self.unitframe:ResetPosition()
	self.unitframe:SetBarWidth(300)
	self.unitframe:SetBarHeight(28)
	self.unitframe:SetBGColor(CColor.new(0,0,0,1))
	self.unitframe:SetBarColor(CColor.new(1,0,0,0.5))
	self.unitframe:SetEnabled(true)
end

function Raiderino:OnBarWidthChanged( wndHandler, wndControl, fNewValue, fOldValue )
	local group = wndHandler:GetParent():GetData()
	group:SetBarWidth(fNewValue)
	wndHandler:GetParent():FindChild("BarWidthValue"):SetText(string.format("%.f", fNewValue))
end

function Raiderino:OnBarWidthValueChanged( wndHandler, wndControl, strText )
	local group = wndHandler:GetParent():GetData()
	local value = tonumber(strText)
	wndHandler:SetText(tostring(value))
	wndHandler:GetParent():FindChild("BarWidth"):SetValue(value)
	group:SetBarWidth(value)
end

function Raiderino:OnBarHeightChanged( wndHandler, wndControl, fNewValue, fOldValue )
	local group = wndHandler:GetParent():GetData()
	group:SetBarHeight(fNewValue)
	wndHandler:GetParent():FindChild("BarHeightValue"):SetText(string.format("%.f", fNewValue))
end

function Raiderino:OnBarHeightValueChanged( wndHandler, wndControl, strText )
	local group = wndHandler:GetParent():GetData()
	local value = tonumber(strText)
	wndHandler:SetText(tostring(value))
	wndHandler:GetParent():FindChild("BarHeight"):SetValue(value)
	group:SetBarHeight(value)
end

function Raiderino:EditGroupBackgroundColor( wndHandler, wndControl, eMouseButton )
	local group = wndHandler:GetParent():GetData()
	local color = group.bgColor
	self.colorPicker:OpenColorPicker(color, function()
		wndHandler:FindChild("Text"):SetTextColor(color)
		group:SetBGColor(color)
	end)
end

function Raiderino:EditGroupBarColor( wndHandler, wndControl, eMouseButton )
	local group = wndHandler:GetParent():GetData()
	local color = group.barColor
	self.colorPicker:OpenColorPicker(color, function()
		wndHandler:FindChild("Text"):SetTextColor(color)
		group:SetBarColor(color)
	end)
end

function Raiderino:OnMoveGroups( wndHandler, wndControl, eMouseButton )
	if wndHandler:GetText() == "Move Groups" then
		wndHandler:SetText("Lock Groups")
		self.notifications:SetMovable(true)
		self.timers:SetMovable(true)
		self.unitframe:SetMovable(true)
	else
		wndHandler:SetText("Move Groups")
		self.notifications:SetMovable(false)
		self.timers:SetMovable(false)
		self.unitframe:SetMovable(false)
	end
end

function Raiderino:OnBarsStartFromTopChanged( wndHandler, wndControl, eMouseButton )
	local group = wndHandler:GetParent():GetData()
	group:AnchorFromTop(wndHandler:IsChecked())
end

function Raiderino:OnEncounterButton( wndHandler, wndControl, eMouseButton )
	local encounterbardata = wndHandler:GetParent():GetData()
	
	local FeaturesList = self.wndMain:FindChild("FeaturesList")
	FeaturesList:DestroyChildren()
	
	for feature, featuredata in pairs(RaiderinoLibs.Encounters[encounterbardata.encounter].features) do
		local featurebar = Apollo.LoadForm(self.xmlDoc, "SubForms.FeatureButton", FeaturesList, self)
		local bardata = {}
		bardata.encounter = encounterbardata.encounter
		bardata.feature = feature
		featurebar:SetData(bardata)
		featurebar:FindChild("Button"):SetText(featuredata.displayname)
		featurebar:FindChild("Button"):FindChild("Enabled"):SetCheck(featuredata.enabled)
	end
	
	FeaturesList:ArrangeChildrenVert()
end

function Raiderino:OnZoneButton( wndHandler, wndControl, eMouseButton )
	local zone = wndHandler:GetText()
	
	local EncountersList = self.wndMain:FindChild("EncountersList")
	EncountersList:DestroyChildren()
	local FeaturesList = self.wndMain:FindChild("FeaturesList")
	FeaturesList:DestroyChildren()
	for encounter, encounterdata in pairs(RaiderinoLibs.Encounters) do
		if encounterdata.zone == zone then
			local encounterbar = Apollo.LoadForm(self.xmlDoc, "SubForms.EncounterButton", EncountersList, self)
			local bardata = {}
			bardata.encounter = encounter
			bardata.position = encounterdata.position
			encounterbar:SetData(bardata)
			encounterbar:FindChild("Button"):SetText(encounterdata.locname)
			encounterbar:FindChild("Enabled"):SetCheck(encounterdata.enabled)
		end
	end
	EncountersList:ArrangeChildrenVert(Window.CodeEnumArrangeOrigin.LeftOrTop, SortEncounters)
end

function Raiderino:OnEncounterEnabledChanged( wndHandler, wndControl, eMouseButton )
	local encounterbardata = wndHandler:GetParent():GetParent():GetData()
	RaiderinoLibs.Encounters[encounterbardata.encounter].enabled = wndHandler:IsChecked()
end

function Raiderino:OnFeatureEnabledChanged( wndHandler, wndControl, eMouseButton )
	local bardata = wndHandler:GetParent():GetParent():GetData()
	
	RaiderinoLibs.Encounters[bardata.encounter].features[bardata.feature].enabled = wndHandler:IsChecked()
end

function Raiderino:OnAdvancedTimers( wndHandler, wndControl, eMouseButton )
	if wndHandler:GetText() == "DEV: Debug On" then
		wndHandler:SetText("DEV: Debug Off")
		self.bDevDebug = true
	else
		wndHandler:SetText("DEV: Debug On")
		self.bDevDebug = false
	end
end

function Raiderino:OnRtest()
	self.UpdateTimer:Start()
	local msg = {text = "This should be 2", maxtime = 20, icon = nil, destroyAtEnd = true}
	self.timers:AddTimer(msg)
	local msg = {text = "This should be 1", maxtime = 10, icon = nil, destroyAtEnd = true}
	self.timers:AddTimer(msg)
	local msg = {text = "This should be 4", maxtime = 40, icon = nil, destroyAtEnd = true}
	self.timers:AddTimer(msg)
	local msg = {text = "This should be 3", maxtime = 30, icon = nil, destroyAtEnd = true}
	self.timers:AddTimer(msg)
	local msg = {text = "PULL IN", maxtime = 10, icon = nil, destroyAtEnd = true}
	self.notifications:AddTimer(msg)
	local options = {unit = GameLib.GetPlayerUnit(), HealthMax = GameLib.GetPlayerUnit():GetMaxHealth(), HealthCurrent = GameLib.GetPlayerUnit():GetHealth(), text = GameLib.GetPlayerUnit():GetName()}
	self.unitframe:AddUnit(options)
	self.testtimer = ApolloTimer.Create(45, false, "OnTest", self)
end
---------------------
-- /FORM FUNCTIONS --
---------------------

-----------------------------------------------------------------------------------------------
-- Raiderino Instance
-----------------------------------------------------------------------------------------------
local RaiderinoInst = Raiderino:new()
RaiderinoInst:Init()
_G["Raiderino"] = RaiderinoInst